﻿#include <iostream>
#include <stdlib.h>
using namespace std;
// 类的六个默认构造函数
// 1.构造函数 2.析构函数 3.拷贝构造函数 4.赋值重载函数 5.6.取地址重载(很少自己实现)

// 默认构造函数：自己不去实现，编译器也会自动生成的函数

// 构造函数
class Stack
{
public:

	void Push(int x)
	{
		if (_size == _capacity)
		{
			int newcapacity = 2 * _capacity;
			int* tmp = (int*)realloc(_a, sizeof(int) * newcapacity);
			if (nullptr == tmp)
			{
				perror("realloc fail!");
				exit(1);
			}

			_a = tmp;
			_capacity = newcapacity;
		}

		_a[_size++] = x;
	}

	// 1.构造函数
	// 函数名与类名一样，无返回值
	// 全缺省构造函数
	// 我们不自己实现构造函数，编译器会默认生成一个无参构造函数，这个函数对内置类型不做处理，对自定义类型会去调用他们的构造函数
	// 无参构造函数，全缺省构造函数，编译器默认生成的无参构造函数都可以称作为默认构造，不传参即可调用的构造为默认构造
	// 相当于Stack中的Init
	Stack(int n = 4)
	{
		cout << "Stack(int n = 4)" << endl;
		_a = (int*)malloc(sizeof(int) * n);
		if (nullptr == _a)
		{
			perror("malloc fail!");
			exit(1);
		}

		_capacity = n;
		_size = 0;
	}

	// 无参构造
	//Stack()
	//{
	//	cout << "Stack()" << endl;
	//	_a = (int*)malloc(sizeof(int) * 4);
	//	if (nullptr == _a)
	//	{
	//		perror("malloc fail!");
	//		exit(1);
	//	}

	//	_capacity = 4;
	//	_size = 0;
	//}

	// 2.析构函数
	// 函数名是类名前加上一个取反符号
	// 析构函数一般实现于有资源申请的类中，一个类中只存在一个析构函数
	// 我们不实现，编译器会自动生成调用析构函数，编译器自己生成的对内置类型不做处理，对自定义类型会去调用他们的构造函数
	// 相当于Stack中的Destroy
	// 如果在定义多个对象的情况下，以栈帧空间为主，后创建的先析构
	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_capacity = _size = 0;
	}

	// 3.拷贝构造函数
	// 拷贝构造函数和构造函数是重载关系
	// 函数名也是类名，不同的是拷贝构造函数第一个参数是自身类型的引用，如果不是引用会出现无穷递归的问题
	// 编译器自动生成的拷贝构造函数属于浅拷贝(值拷贝)，也就是一个字节一个字节的拷贝，对于没有资源申请的可以不用自己实现
	// 对于有资源申请的，我们需要自己实现拷贝构造函数进行深拷贝
	// 如果⼀个类显示实现了析构并释放资源，那么他就需要显⽰写拷贝构造，否则就不需要。
	// 如果像栈这样的需要深拷贝的，我们不去实现使用编译器生成的，最后两个对象会指向同一快空间，会析构两次产生报错
	Stack(const Stack& st) // 这边写const防止修改拷贝的来源值
	{
		cout << "Stack(const Stack& st)" << endl;
		_a = (int*)malloc(sizeof(int) * st._capacity);
		if (nullptr == _a)
		{
			perror("malloc fail!");
			exit(1);
		}
		memcpy(_a, st._a, sizeof(int) * st._size);
		_capacity = st._capacity;
		_size = st._size;
	}
	
private:
	int* _a;
	int _capacity;
	int _size;
};

int main()
{
	// 这边我们不去调用，构造函数自动调用进行初始化
	Stack st; // 对象实例化
	st.Push(1);
	st.Push(2);

	Stack st2(st);
	/*cout << &st << endl;
	cout << &st2 << endl;*/

	return 0;
}
